package com.mbigger.netty.ch8;

import com.mbigger.netty.ch8.in.InBoundHandler;
import com.mbigger.netty.ch8.out.DelimiterEncoder;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.compression.JdkZlibDecoder;
import io.netty.handler.codec.compression.JdkZlibEncoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class NettyServer {
    /**
     * 在端口绑定失败之后，重新调用自身方法，并且把端口号加一
     * 
     * @param serverBootstrap
     *            TCP Server 启动辅助类
     * @param port
     *            需要绑定的端口号
     */

    private static void bind(final ServerBootstrap serverBootstrap, final int port) {
        serverBootstrap.bind(port).addListener(new GenericFutureListener<Future<? super Void>>() {
            public void operationComplete(Future<? super Void> future) {
                ChannelFuture channelFuture = (ChannelFuture) future;
                Channel channel = channelFuture.channel();
                if (future.isSuccess()) {
                    log.info("绑定成功, 本地地址[{}]", channel.localAddress());
                } else {
                    log.error("端口[{}]绑定失败, 失败原因: {}", port, future.cause().getMessage());
                    bind(serverBootstrap, port + 1);
                }
            }
        });
    }

    public static void main(String[] args) {

        int port = 49664;

        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();

        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.handler(new ChannelInitializer<NioServerSocketChannel>() {
            protected void initChannel(NioServerSocketChannel ch) {
                System.out.println("服务端启动中...");
            }
        });
        serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    protected void initChannel(NioSocketChannel ch) {
                        log.info("init channel !");
                        // 处理读数据的逻辑链
                        ByteBuf delimiter = Unpooled.copiedBuffer(Constants.TAIL);
                        ch.pipeline().addLast(new DelimiterBasedFrameDecoder(2048, delimiter));
                        ch.pipeline().addLast(new JdkZlibDecoder());
                        ch.pipeline().addLast(new StringDecoder());
                        ch.pipeline().addLast(new InBoundHandler());

                        // 写逻辑处理
                        ch.pipeline().addLast(new DelimiterEncoder());
                        ch.pipeline().addLast(new JdkZlibEncoder());
                        ch.pipeline().addLast(new StringEncoder());

                    }
                });

        bind(serverBootstrap, port);

    }
}
